﻿

#include "stdafx.h"

void idTrans(const TCHAR *in, TCHAR *out)
{
	for(int i = 0; i< ID_LEN; i++){
		out[i] = TEXT('0') + in[i];
		if(!_istdigit(out[i])){
			for(int i = 0; i< ID_LEN; i++)
				out[i] = TEXT('F');

			break;
		}
	}

	out[ID_LEN] = 0;
}

unsigned char HIDSpeed(unsigned speed)
{
	//1=300(ucRate为1时对应波特率300),2=600,3=1200,4=2400,5=4800,6=9600(默认值),7=14400,
	//	8=19200,9=28800,10=38400,11=57600,12=76800,13=115200
	unsigned char	ucRate = 6;
	switch(speed){
		case 300:
			ucRate = 1;
			break;
		case 600:
			ucRate = 2;
			break;
		case 1200:
			ucRate = 3;
			break;
		case 2400:
			ucRate = 4;
			break;
		case 4800:
			ucRate = 5;
			break;
		case 9600:
			ucRate = 6;
			break;
		case 14400:
			ucRate = 7;
			break;
		case 19200:
			ucRate = 8;
			break;
		case 28800:
			ucRate = 9;
			break;
		case 38400:
			ucRate = 10;
			break;
		case 57600:
			ucRate = 11;
			break;
		case 76800:
			ucRate = 12;
			break;
		case 115200:
			ucRate = 13;
			break;
	}

	return ucRate;
}

unsigned chrMask()
{
	unsigned mask = (unsigned)(-1);
	switch(sizeof(TCHAR)){
		case 1:
			mask = 0xff;
			break;
		case 2:
			mask = 0xffff;
			break;
		case 4:
			mask = 0xffffffff;
			break;
	}

	return mask;
}

unsigned chrVal(TCHAR c)
{
	return c&chrMask();
}

msgBuffer::msgBuffer(HWND hWnd, unsigned size)
{
	m_size = size;
	m_len = 0;
	m_buf = (char*)malloc(m_size);
	m_hMainWnd = hWnd;

	m_fn = 0;
	m_arg = 0;
	ASSERT(m_buf);
}

msgBuffer::~msgBuffer()
{
	free(m_buf);
}

char* msgBuffer::getMsgStart(char *buf, unsigned len)
{
	for(unsigned i = 0; i < len; i++){
		if(buf[i] == MSG_BEGIN && i+2 < len)
			return buf+i;
	}

	return 0;
}

int msgBuffer::processMsg(char *start, unsigned size, unsigned len)
{
	if(len > size)
		return 0;

	void *p = malloc(len);
	if(!p)
		return len;

	//::PostMessage(GetSafeHwnd(), WM_USER_THREADEND, 0, 0);
	//CWnd *pMainWnd = AfxGetMainWnd();pMainWnd->m_hWnd
	//::PostMessage(data->hand, WM_USER_THREADEND, (WPARAM)p, len);
	memcpy(p, start, len);
	
#if DEBUG_TEST
	CString text;
	HWND mhMainWnd = AfxGetMainWnd()->m_hWnd;
	if(m_hMainWnd != mhMainWnd){
		
		text.Format(TEXT("mhMainWnd=%d,m_hMainWnd=%d"), mhMainWnd, m_hMainWnd);

		MessageBox(0, text.GetBuffer(0), TEXT("processMsg err"), MB_ICONINFORMATION|MB_YESNO);
	}else{
		msgXData(text, start, len);
		MessageBox(0, text.GetBuffer(0), TEXT("processMsg"), MB_ICONINFORMATION|MB_YESNO);
	}
#endif

	if(m_fn)
		m_fn(start[2], start, len, m_arg);
	::PostMessage(m_hMainWnd, WM_USER_THREADEND, (WPARAM)p, len);
	return len;
}

int msgBuffer::getMsgOne(char *buf, unsigned len)
{
	CString debug;
	char* start = getMsgStart(buf, len);
	if(!start){
		return 0;
	}

	int offset = (start - buf);
	ASSERT(offset >= 0 && len >= offset);
	len -= offset;
	
	switch(start[2]){
		case TEXT('\x2'):	//答题对
			return offset+processMsg(start, len, 18);
		case TEXT('\x5'):	//考勤
			msgXData(debug, start, 15);
			return offset+processMsg(start, len, 15);
		case TEXT('\x4'):	//开考勤
		case TEXT('\x6'):	//关考勤
		case TEXT('\x1'):	//开答题
		case TEXT('\x3'):	//关答题
			return offset+processMsg(start, len, 3);
		case TEXT('\x7'):	//校时
			return offset+processMsg(start, len, 6);
		case TEXT('\xb'):	//关考勤
			return offset+processMsg(start, len, 14);
		default:
			return -1;
	}

	return -1;
}

unsigned msgBuffer::getMsg()
{
	int ret = 0;
	
	while(1){
		ASSERT(m_len >= ret);
		int err = getMsgOne(m_buf + ret, m_len - ret);
		if(0 > err){
			return m_len;
		}
		if(0 == err)
			return ret;

		ret += err;
	}
	
	return m_len;
}

bool msgBuffer::addInput(char *buf, unsigned size)
{
	if(m_len + size >= m_size){
		m_len = 0;
		return false;
	}

	memcpy(m_buf + m_len, buf, size);
	m_len += size;

	unsigned len = getMsg();
	if(!len && m_len < m_size/2)
		return true;

	ASSERT(m_len >= len);
	m_len -= len;
	memmove(m_buf, m_buf+len, m_len);
	return true;
}

void msgXData(CString &str, TCHAR *in, unsigned len)
{
	unsigned mask = chrMask();

	TCHAR buffer[2048];

	ASSERT(sizeof(buffer)/sizeof(buffer[0]) > len+1);
	unsigned i;
	for(i = 0; i < len; i++){
		_stprintf(buffer + 2*i, TEXT("%02x"), chrVal(in[i]));
	}

	str = CString(buffer) + TEXT("\r\n") + str;
}

void elecTrans(int e, TCHAR *in)
{
	switch(e){
		case 0:
		_tcscpy(in, TEXT("2.7V"));
		break;
		case 1:
		_tcscpy(in, TEXT("2.7V"));
		break;
		case 2:
		_tcscpy(in, TEXT("2.8V"));
		break;
		case 3:
		_tcscpy(in, TEXT("2.9V"));
		break;
		case 4:
		_tcscpy(in, TEXT("3.0V"));
		break;
		case 5:
		_tcscpy(in, TEXT("3.0V"));
		break;
		default:
		_tcscpy(in, TEXT("0.0V"));
		break;
	}
}


int toLocalCode(const char *in, unsigned inlen, TCHAR *out, unsigned outlen)
{
#ifdef _UNICODE
	TCHAR *tmp = out;
	if(in != out){
		tmp = malloc(sizeof(outlen)*sizeof(TCHAR));
	}

	if(!tmp)
		return 0;
	
	int ret = MultiByteToWideChar(CP_ACP, NULL, in, inlen, tmp, outlen); 
	if(in != out)
		memcpy(out, tmp);

	return ret;
#else

	if(outlen < inlen)
		return 0;

	if(in != out)
		memmove(out, in, inlen);

	return inlen;
#endif
}

int toUtf8(const TCHAR *in, unsigned inlen, char *out, unsigned outlen)
{
#ifdef _UNICODE
	TCHAR *tmp = out;
	if(in != out){
		tmp = malloc(sizeof(outlen));
	}

	if(!tmp)
		return 0;
	
	int ret = WideCharToMultiByte(CP_ACP, NULL, in, inlen, tmp, outlen); 
	if(in != out)
		memcpy(out, tmp);

	return ret;
#else

	if(outlen < inlen)
		return 0;

	if(in != out)
		memmove(out, in, inlen);

	return inlen;
#endif	
}

bool isSystemType()
{
	OSVERSIONINFOEX os;
	os.dwOSVersionInfoSize=sizeof(OSVERSIONINFOEX); 
	GetVersionEx((OSVERSIONINFO *)&os);
	
	return os.dwMajorVersion > 1;
}

void readFileString(CString filePath, set<CString> &s)
{
	CStdioFile File;
	if(!File.Open(filePath, CFile::modeRead))
		return;

	CString   strLine;
	while(File.ReadString(strLine)){
		if(strLine.GetLength() == ID_LEN)
			s.insert(strLine);
	}

	File.Close();
}

void writeFileString(CString filePath, set<CString> &s)
{
	CStdioFile File;
	if(!File.Open(filePath, CFile::modeCreate|CFile::modeWrite))
		return;

	for(set<CString>::iterator it = s.begin(); it != s.end(); it++){
		File.WriteString(*it);
		File.WriteString("\n");
	}

	File.Close();
}

void readFileMap(CString filePath, map <CString, bool>  &s)
{
	CStdioFile File;
	if(!File.Open(filePath, CFile::modeRead))
		return;

	CString   strLine;
	while(File.ReadString(strLine)){
		CString   id;
		CString   val;

		AfxExtractSubString(id, strLine, 0, ',');
		AfxExtractSubString(val, strLine, 1, ',');
		
		s[id] = _ttoi(val);
	}

	File.Close();
}

void writeFileMap(CString filePath, map <CString, bool>  &s)
{
	CStdioFile File;
	if(!File.Open(filePath, CFile::modeCreate|CFile::modeWrite))
		return;

	CString line;
	for(map <CString, bool>::iterator it = s.begin(); it != s.end(); it++){
		line.Format(TEXT("%s,%d"), it->first, it->second);
		File.WriteString(line);
		File.WriteString("\n");
	}

	File.Close();
}

class anwerOnoff s_onoff;
const bool  anwerOnoff::m_allOff = false;

anwerOnoff::anwerOnoff()
{
	m_mutex.Lock();

	writeFileMap("answerOnoff.ini", m_anwerOnoff);

	m_mutex.Unlock();
}

void anwerOnoff::on(const CString &id)
{
	m_mutex.Lock();

	m_anwerOnoff[id] = true;
	writeFileMap("answerOnoff.ini", m_anwerOnoff);

	m_mutex.Unlock();
}

void anwerOnoff::off(const CString &id)
{
	m_mutex.Lock();

	m_anwerOnoff[id] = false;
	writeFileMap("answerOnoff.ini", m_anwerOnoff);

	m_mutex.Unlock();
}

void anwerOnoff::onAll()
{
	m_mutex.Lock();

	for(map <CString, bool>::iterator it = m_anwerOnoff.begin(); it != m_anwerOnoff.end(); it++){
		it->second = true;
	}

	writeFileMap("answerOnoff.ini", m_anwerOnoff);

	m_mutex.Unlock();
}

void anwerOnoff::offAll()
{
	m_mutex.Lock();

	for(map <CString, bool>::iterator it = m_anwerOnoff.begin(); it != m_anwerOnoff.end(); it++){
		it->second = false;
	}

	writeFileMap("answerOnoff.ini", m_anwerOnoff);

	m_mutex.Unlock();
}

bool anwerOnoff::arrowOff(const CString &id)
{
	bool ret = true;
	m_mutex.Lock();

	map <CString, bool>::iterator it = m_anwerOnoff.find(id);
	if(it != m_anwerOnoff.end())
		ret = it->second;
	else
		ret = m_allOff;

	m_mutex.Unlock();

	return ret;
}

bool arrowOff(const CString &id)
{
	return s_onoff.arrowOff(id);
}

void anwerOn(const CString &id)
{
	s_onoff.on(id);
}

void anwerOff(const CString &id)
{
	s_onoff.off(id);
}

void anwerOnAll()
{
	s_onoff.onAll();
}

void anwerOffAll()
{
	s_onoff.offAll();
}


int timeEchoMsg(TCHAR *buf, unsigned size)
{
	SYSTEMTIME st;
	GetLocalTime(&st);

	buf[0] = (TCHAR)('\x7f');
	buf[1] = (TCHAR)('\x32');
	buf[2] = (TCHAR)('\x07');

	buf[3] = (TCHAR)(st.wHour&0xff);
	buf[4] = (TCHAR)(st.wMinute&0xff);
	buf[5] = (TCHAR)((st.wHour+st.wMinute)&0xff);

	return 6;
}

